package com.aivin.myapplication;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

//  自定义 独占锁
public class MyLock implements Lock {
    private final MyAQS sync =new MyAQS();;

    static class MyAQS extends AbstractQueuedSynchronizer {

        @Override
        protected boolean tryAcquire(int acquires) {
            final Thread currentThread = Thread.currentThread();
            int currentState = getState();
            if (currentState == 0) {
                // cas 方式设置同步状态
                if ( compareAndSetState(0, acquires)) {
                    //设置当前线程独占访问权限
                    setExclusiveOwnerThread(currentThread);
                    return true;
                }
            }
            //判断当前线程是否有访问权限，对可重入锁的支持
            else if (currentThread == getExclusiveOwnerThread()) {
                //累加后更新state值
                int nextc = currentState + acquires;
                if (nextc < 0){
                    // overflow , 超过的最大锁数
                    throw new Error("Maximum lock count exceeded");
                }
                setState(nextc);
                return true;
            }
            return false;
        }

        @Override
        protected boolean tryRelease(int releases) {
            //释放锁就是更新释放后的state值，如果当前线程已经没有持有锁，就把去除独占状态
            int currentState = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread()){
                throw new IllegalMonitorStateException();
            }

            boolean free = false;
            if (currentState == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(currentState);
            return free;
        }
    }

    @Override
    public void lock() {
        //可以理解为请求获取一把锁 , 最后会调用到 tryAcquire
        sync.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock() {
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }

    @Override
    public void unlock() {
         // 调用AQS中的模板方法 释放锁 , 会调用到 自定义的 tryRelease()
        sync.release(1);
    }

    @Override
    public Condition newCondition() {
        return null;
    }
}